﻿<%@ Page  Trace="false" Language="C#" MasterPageFile="~/vboard/manager/main.master" Inherits="VioletDevelopmentLaboratory.Net.Web.PageBase" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Collections.ObjectModel" %>

<script runat="server">
	/// <summary>
	/// 폴더 또는 파일정보를 저장할 클래스
	/// </summary>
	private class DirectoryItem
	{
		public DirectoryItem() { }

		private bool isFile;
		public bool IsFile { get { return isFile; } set { isFile = value; } }
		
		private string name;
		public string Name { get { return name; } set { name = value; } }

		private string extension;
		public string Extension { get { return extension; } set { extension = value; } }

		private string length;
		public string Length { get { return length; } set { length = value; } }

		private string directoryFullName;
		public string DirectoryFullName { get { return directoryFullName; } set { directoryFullName = value; } }

		private DateTime creationTime;
		public DateTime CreationTime { get { return creationTime; } set { creationTime = value; } }

		private DateTime lastAccessTime;
		public DateTime LastAccessTime { get { return lastAccessTime; } set { lastAccessTime = value; } }

		private DateTime lastWriteTime;
		public DateTime LastWriteTime { get { return lastWriteTime; } set { lastWriteTime = value; } }
	}
	/// <summary>
	/// 설정된 폴더에 존재하는 모든 폴더와 파일 목록을 저장할 컬렉션
	/// (예전에는 컬렉션도 만들어 사용했는데 이제는 간단하게 제네릭으로 ^^)
	/// </summary>
	private class DirectoryItemCollection : Collection<DirectoryItem> { }

	protected void Page_Load(object sender, EventArgs e)
	{
		//페이지가 처음 로딩되면 웹에플리케이션 루트의 폴더와 파일 바인드
		if (!Page.IsPostBack)
		{
			CurrentFolderLabel.Text = Request.PhysicalApplicationPath;

			Directories_Bind(Request.PhysicalApplicationPath);
		}
	}

	/// <summary>
	/// 파일 확장명에 따라 아이콘 파일 이름을 반환합니다.
	/// (icon_확장명.gif)
	/// </summary>
	/// <param name="extension">파일 확장명</param>
	/// <returns>아이콘 파일 이름</returns>
	private string selectIcon(string extension)
	{
		if(string.IsNullOrEmpty(extension))
			return "folder.gif";
		
		return string.Format("{0}.gif", extension);
	}

	/// <summary>
	/// 폴더/파일목록을 바인드합니다.
	/// </summary>
	/// <param name="folderPath">폴더</param>
	private void Directories_Bind(string folderPath)
	{
		//현재위치
		CurrentFolderLabel.Text = folderPath;

		//상위폴더 이동 버튼
		UpButton.Visible = !(folderPath.ToLower() == Request.PhysicalApplicationPath.ToLower());
		UpButton.CommandArgument = (new DirectoryInfo(folderPath)).Parent.FullName + @"\";

		//폴더,파일 목록을 저장할 변수
		DirectoryItemCollection itemCollection = new DirectoryItemCollection();
		DirectoryItem item = null;

		//폴더 목록을 컬렉션에 추가
		int folderCount = 0;
		DirectoryInfo dir = null;
		foreach (string path in Directory.GetDirectories(folderPath))
		{
			dir = new DirectoryInfo(path);

			item = new DirectoryItem();
			item.IsFile = false;//폴더인지 파일인지 구분할 플래그. 지금은 폴더이므로 false.
			item.Name = dir.Name;//폴더이름
			item.Extension = dir.Extension;//폴더이므로 확장명은 없어요.
			item.DirectoryFullName = dir.FullName + @"\";//폴더전체경로. 끝에 원기호를 붙여줍니다.
			item.CreationTime = dir.CreationTime;//폴더 생성한 날짜
			item.LastAccessTime = dir.LastAccessTime;//폴더 접근한 날짜
			item.LastWriteTime = dir.LastWriteTime;//폴더 변경한 날짜

			//컬렉션에 추가
			itemCollection.Add(item);

			folderCount++;
		}

		//폴더를 추가했으니 이제는 파일 목록도 컬렉션에 추가
		int fileCount = 0;
		FileInfo file = null;
		foreach (string path in Directory.GetFiles(folderPath))
		{
			file = new FileInfo(path);

			item = new DirectoryItem();
			item.IsFile = true;//지금은 파일이므로 true.
			item.Name = file.Name;//파일이름
			item.Extension = file.Extension.ToLower().Substring(1);//확장명. 앞에 온점 제거.
			item.Length = VUtility.GetFormatFileLength(file.Length);//파일크기는 단위를 붙인 문자열로 포멧.
			item.DirectoryFullName = file.DirectoryName;//파일이 있는 폴더의 전체경로. 파일이름은 생략하고 순수 폴더경로만.
			item.CreationTime = file.CreationTime;//파일 생성한 날짜
			item.LastAccessTime = file.LastAccessTime;//파일 접근한 날짜
			item.LastWriteTime = file.LastWriteTime;//파일 변경한 날짜

			//컬렉션에 추가
			itemCollection.Add(item);

			fileCount++;
		}

		//그리드뷰 바인드
		GridView1.DataSource = itemCollection;
		GridView1.DataBind();

		//폴더와 파일 개수 출력
		FolderCountLabel.Text = folderCount.ToString();
		FileCountLabel.Text = fileCount.ToString();
		
		//바인드한 시간 출력
		LastLoadingDate.Text = DateTime.Now.ToString();
	}

	/// <summary>
	/// 그리드뷰 목록에서 폴더 또는 파일을 클릭하면 폴더 이동 또는 다운로드
	/// </summary>
	/// <param name="sender">이벤트 일으킨 놈</param>
	/// <param name="e">이벤트 정보</param>
	protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
	{
		//명령이 폴더인지 파일인지 확인해서
		//폴더이면 해당 폴더로 이동하고
		//파일이면 해당 파일을 다운로드 합니다.
		if (e.CommandName == "Dir")
		{
			Directories_Bind(e.CommandArgument.ToString());
		}
		else if (e.CommandName == "File")
		{
			//다운로드 핸들러에 파일 전체경로 넘겨줍니다.
			Response.Redirect("download.ashx?file=" + Server.UrlEncode(e.CommandArgument.ToString()), true);
		}
		else
		{
			VUtility.ShowMessagePanel(Page, "알 수 없는 명령입니다.", true);
		}
	}

	protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
	{
		if (e.Row.RowType == DataControlRowType.DataRow)
		{
			//현재행의 데이터 가져오기
			DirectoryItem item = (DirectoryItem)e.Row.DataItem;

			//폴더 또는 파일 이름 버튼 가져오기
			LinkButton nameLinkButton = (LinkButton)e.Row.FindControl("NameLinkButton");
			nameLinkButton.Text = item.Name;//폴더 또는 파일이름 출력

			//폴더인지 파일인지 확인해서
			if (!item.IsFile)
			{
				//명령은 Dir, 변수는 폴더전체경로
				nameLinkButton.CommandName = "Dir";
				nameLinkButton.CommandArgument = item.DirectoryFullName;

				//폴더행은 색깔을 노랗게 설정
				if (e.Row.RowState == DataControlRowState.Normal)
					e.Row.CssClass = "FolderRowCssClass";
				else
					e.Row.CssClass = "FolderAlternatingRowCssClass";
			}
			else
			{
				//명령은 File, 변수는 파일전체경로
				nameLinkButton.CommandName = "File";
				nameLinkButton.CommandArgument = Path.Combine(item.DirectoryFullName, item.Name);
			}

			//단순 목록에 폴더,파일 종류에 따라 아이콘 출력
			Image typeImage = (Image)e.Row.FindControl("TypeImage");

			//ASP.NET 예약 폴더 아이콘
			if ("app_browsers app_code app_data app_globalresources app_localresources app_themes app_webreferences bin".IndexOf(item.Name.ToLower()) > -1)
				typeImage.ImageUrl = string.Format("~/vboard/common/image/icon/{0}", this.selectIcon(item.Name));//ASP.NET 예약 폴더 아이콘
			else
				typeImage.ImageUrl = string.Format("~/vboard/common/image/icon/{0}", this.selectIcon(item.Extension));//보통 폴더 또는 파일 아이콘

			//아이콘중에 일치하는 이름이 없으면 일반적 아이콘으로 변경
			typeImage.Attributes.Add("onerror", string.Format("javascript:this.src='{0}'", ResolveClientUrl("~/vboard/common/image/icon/general.gif")));
		}
	}

	/// <summary>
	/// 현제 폴더에 파일을 업로드 합니다.
	/// </summary>
	/// <param name="sender">업로드 버튼</param>
	/// <param name="e">이벤트 변수</param>
	protected void AddFileButton_Click(object sender, EventArgs e)
	{
		//파일업로드 컨트롤에 파일이 있는지 확인
		if (FileUpload1.HasFile)
		{
			string saveFilePath = "";

			//파일 이름이 겹치지 않도록해서 저장
			PhysicalFileManager fileManager = new PhysicalFileManager(CurrentFolderLabel.Text);
			fileManager.Save(FileUpload1.PostedFile, out saveFilePath);

			//목록 다시 바인드
			Directories_Bind(CurrentFolderLabel.Text);

			VUtility.ShowMessagePanel(Page, saveFilePath + " 저장됨", true);
		}
		else
			VUtility.ShowMessagePanel(Page, "파일이 없습니다.", true);
	}

	/// <summary>
	/// 상위 폴더로 이동합니다.
	/// </summary>
	/// <param name="sender">위로 버튼</param>
	/// <param name="e">이벤트 변수</param>
	protected void UpButton_Click(object sender, EventArgs e)
	{
		//상위 폴더로 바꿔서 목록 다시 바인드
		Directories_Bind(UpButton.CommandArgument.ToString());
	}

	/// <summary>
	/// 현재 목록을 새로고침니다.
	/// </summary>
	/// <param name="sender">새로고침 버튼</param>
	/// <param name="e">이벤트 변수</param>
	protected void ReloadButton_Click(object sender, EventArgs e)
	{
		Directories_Bind(CurrentFolderLabel.Text);
	}

	/// <summary>
	/// 선택한 폴더 또는 파일을 삭제합니다.
	/// </summary>
	/// <param name="sender">삭제 버튼</param>
	/// <param name="e"></param>
	protected void RemoveButton_Click(object sender, EventArgs e)
	{
		string removeItems = "";

		LinkButton nameLinkButton = null;
		DirectoryInfo removeDir = null;
		FileInfo removeFile = null;

		//그리드뷰의 행을 돌면서
		foreach (GridViewRow row in GridView1.Rows)
		{
			//현재행이 선택되었는지 확인
			if (((CheckBox)row.FindControl("ItemCheckBox")).Checked)
			{
				//목록에 있는 링크버튼으로부터 폴더 또는 파일 정보를 가져옵니다.
				nameLinkButton = (LinkButton)row.FindControl("NameLinkButton");
				removeItems += nameLinkButton.CommandArgument.Replace(@"\", @"\\");

				//파일이면
				if (nameLinkButton.CommandName == "File")
				{
					removeFile = new FileInfo(nameLinkButton.CommandArgument);
					if (removeFile.Exists)
					{
						try
						{
							// 파일삭제
							removeFile.Delete();
							removeItems += " - 삭제성공";
						}
						catch (Exception ex)
						{
							removeItems += " - 삭제실패:" + ex.Message;
						}
					}
					else
						removeItems += " - 삭제실패:파일없음";
				}
				else
				{
					//폴더면 폴더 삭제
					removeDir = new DirectoryInfo(nameLinkButton.CommandArgument);

					if (removeDir.Exists)
					{
						try
						{
							//폴더 자식들도 삭제.
							removeDir.Delete(true);
							removeItems += " - 삭제성공";
						}
						catch (Exception ex)
						{
							removeItems += " - 삭제실패:" + ex.Message;
						}
					}
					else
						removeItems += " - 삭제실패:폴더없음";
				}

				removeItems += "<br />";
			}
		}

		//목록 다시 바인드
		Directories_Bind(CurrentFolderLabel.Text);

		//결과 출력
		VUtility.ShowMessagePanel(Page, removeItems, true);
	}

	/// <summary>
	/// 현재위치에 새 폴더를 만듭니다.
	/// </summary>
	/// <param name="sender">새 폴더 버튼</param>
	/// <param name="e">이벤트 변수</param>
	protected void AddFolderButton_Click(object sender, EventArgs e)
	{
		if (Page.IsValid)
		{
			try
			{
				//지정된 이름으로 폴더 생성
				Directory.CreateDirectory(Path.Combine(CurrentFolderLabel.Text, FolderNameTextBox.Text));

				FolderNameTextBox.Text = "";

				//목록 다시 바인드
				Directories_Bind(CurrentFolderLabel.Text);

				//결과 출력
				VUtility.ShowMessagePanel(Page, FolderNameTextBox.Text + " - 폴더 생성 성공", true);
			}
			catch (Exception ex)
			{
				VUtility.ShowMessagePanel(Page, FolderNameTextBox.Text + " - 폴더 생성 실패:" + ex.Message, true);
			}
		}
	}
</script>

<asp:Content ID="Content1" ContentPlaceHolderID="BodyContentPlaceHolder" Runat="Server">

	<div>
		<asp:TextBox ID="FolderNameTextBox" runat="server" MaxLength="255" ValidationGroup="AddFolder" />
		<asp:Button ID="AddFolderButton" runat="server" Text="새 폴더" onclick="AddFolderButton_Click" ValidationGroup="AddFolder" />
		<asp:RequiredFieldValidator ID="FolderNameTextBoxRequiredFieldValidator" 
			runat="server" ControlToValidate="FolderNameTextBox" Display="Dynamic" 
			ErrorMessage="새 폴더 이름을 입력하세요." ValidationGroup="AddFolder"></asp:RequiredFieldValidator>
		(현재위치에 폴더를 만듭니다. 폴더이름에 사용할 수 없는 문자들 : \ / : * ? " &lt; &gt; |)
	</div>

	<div>
		<asp:FileUpload ID="FileUpload1" runat="server" />
		<asp:Button ID="AddFileButton" runat="server" Text="업로드" 
			onclick="AddFileButton_Click" OnClientClick="javascript:VWebGlobal_ShowMessageCustomPanel('VWeb_BoardFileUploadingPanel', false);" />
		(현재폴더에 파일을 업로드합니다.)
	</div>

	<div>
		현재위치 : <asp:Label ID="CurrentFolderLabel" runat="server" />
	</div>

	<div>
		폴더 : <asp:Label ID="FolderCountLabel" runat="server" />개 |
		파일 : <asp:Label ID="FileCountLabel" runat="server" />개 |
		로딩한 날짜 : <asp:Label ID="LastLoadingDate" runat="server" />
	</div>

	<asp:Button ID="UpButton" runat="server" Text="위로" onclick="UpButton_Click" />
	<asp:Button ID="ReloadButton" runat="server" Text="새로고침" onclick="ReloadButton_Click" />
	<asp:Button ID="RemoveButton" runat="server" Text="선택삭제" onclick="RemoveButton_Click" OnClientClick="<%$ Resources:VGlobalResources, General_Script_RemoveConfirm %>" />

	<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" 
		onrowcommand="GridView1_RowCommand" onrowdatabound="GridView1_RowDataBound" 
		Width="100%" CellPadding="2" GridLines="None" ShowFooter="true" EmptyDataText="폴더, 파일이 없습니다.">
		<HeaderStyle BackColor="LightGray" />
		<FooterStyle BackColor="LightGray" />
		<RowStyle CssClass="FileRowCssClass" />
		<AlternatingRowStyle CssClass="FileAlternatingRowCssClass" />
		<EmptyDataRowStyle BackColor="LightGray" />
		<Columns>
			<asp:TemplateField ItemStyle-HorizontalAlign="Center">
				<HeaderTemplate>
					<input id="SelectAllCheckBox" type="checkbox" value="" onclick="javascript:VWebGlobal_SelectCheckBox(this, '<%= GridView1.ClientID %>', 'ItemCheckBox');" /><label for="SelectAllCheckBox">전체</label>
				</HeaderTemplate>
				<ItemTemplate>
					<asp:CheckBox ID="ItemCheckBox" runat="server" />
				</ItemTemplate>
			</asp:TemplateField>
			<asp:TemplateField HeaderText="이름">
				<ItemTemplate>
					<asp:Image ID="TypeImage" runat="server" ImageAlign="Top" Width="18px" Height="18px" />
					<asp:LinkButton ID="NameLinkButton" runat="server" />
				</ItemTemplate>
			</asp:TemplateField>
			<asp:BoundField DataField="Length" HeaderText="크기" ItemStyle-HorizontalAlign="Right" />
			<asp:BoundField DataField="CreationTime" HeaderText="생성한 날짜" HeaderStyle-HorizontalAlign="Left" />
			<asp:BoundField DataField="LastAccessTime" HeaderText="엑세스한 날짜" HeaderStyle-HorizontalAlign="Left" />
			<asp:BoundField DataField="LastWriteTime" HeaderText="저장한 날짜" HeaderStyle-HorizontalAlign="Left" />
		</Columns>
	</asp:GridView>

<!-- 이상 끝. //-->
</asp:Content>